/**
 * @file HAL_Uart3.c
 * @brief 
 * @author Mr.
 * @version V1.0
 * @date 2023-02-24
 * 
 * @copyright Copyright (c) 2023  ���Ź����������������˿Ƽ����޹�˾
 * 
 * @par �޸���־:
 * <table>
 * <tr><th>Date   <th>Version <th>Author <th>Description
 * <tr><td>2023-02-24 <td>V1.0     <td>Mr.    <td>������ʼ�汾
 * </table>
 */

#include "HAL_Uart1.h"



Uart1_RxBuffer_t Uart1_RxBuffer = {0};
Uart1_RxBuffer_t Uart3_RxBuffer = {0};


extern UART_HandleTypeDef huart1;
extern UART_HandleTypeDef huart3;
extern DMA_HandleTypeDef hdma_usart1_rx;
extern DMA_HandleTypeDef hdma_usart3_rx;


extern uint8_t devID;


extern moreCoilData mMoreCoidData;
extern oneCoilData mOneCoidData1;
extern oneCoilData mOneCoidData2;
extern oneCoilData mOneCoidData3;
extern oneCoilData mOneCoidData4;
extern oneCoilData mOneCoidData5;
extern oneCoilData mOneCoidData6;
extern oneCoilData mOneCoidData7;
extern oneCoilData mOneCoidData8;

extern uint8_t min_lock_state;    //按下是0需要延时,否者不需要延时
extern uint8_t max_lock_state;    //上合是1
extern uint8_t open_dev_state;

/*
 * @funNm
 * @brief
 * @param
 * @retval
 */

uint16_t modbus_crc(uint8_t *data, size_t length)
{
	uint16_t crc = 0xFFFF;  // 初始化CRC寄存器为0xFFFF
	uint8_t i;

	// 遍历数据字节
	for (size_t j = 0; j < length; j++) {
		crc ^= data[j];  // 将字节与CRC寄存器进行异或运算
		// 对每个字节进行8次操作
		for (i = 0; i < 8; i++) {
			if (crc & 0x0001) {
				crc >>= 1;  // 右移一位
				crc ^= 0xA001;  // 多项式0xA001与CRC寄存器异或
			} else {
				crc >>= 1;  // 右移一位
			}
		}
	}
	return crc;  // 返回计算的CRC值
}

// 计算并输出Modbus CRC的低字节和高字节
uint8_t print_modbus_crc(uint8_t *data, size_t length) {

	if(length < 2)
		return 0;

	uint16_t crc = modbus_crc(data, length -2);
	uint8_t crcL = (crc & 0xFF);
	uint8_t crcH = ((crc >> 8) & 0xFF);
	if((crcL == data[length - 2])&&(crcH == data[length - 1]))
	{
		return 1;
	}else{
		return 0;
	}
}

uint16_t calculate_crc(uint8_t *data, size_t length) {
	// CRC16-IBM计算方法
	uint16_t crc = 0xFFFF;
	for (size_t i = 0; i < length; i++) {
		crc ^= data[i];
		for (int j = 8; j != 0; j--) {
			if (crc & 0x0001) {
				crc >>= 1;
				crc ^= 0xA001;
			} else {
				crc >>= 1;
			}
		}
	}
	return crc;
}


void create_modbus_05_response(uint8_t *response_buffer, Modbus05Request *request)
{
	Modbus05Response response = {
			.address = request->address,
			.function_code = request->function_code,
			.coil_address = request->coil_address,
			.coil_status = request->coil_status
	};

	response.crc = calculate_crc((uint8_t *)&response, sizeof(Modbus05Response) - 2);

	memcpy(response_buffer, &response, sizeof(Modbus05Response));
}


void create_modbus_0F_response(uint8_t *response_buffer, Modbus0FRequest *request) {
	Modbus0FResponse response = {
			.address = request->address,
			.function_code = request->function_code,
			.starting_address = request->starting_address,
			.quantity_of_coils = request->quantity_of_coils
	};

	response.crc = calculate_crc((uint8_t *)&response, sizeof(Modbus0FResponse) - 2);
	memcpy(response_buffer, &response, sizeof(Modbus0FResponse));
}


/**
 * @funNm
 * @brief  ���ڳ�ʼ��
 * @param	void
 * @retval void
 */
void HAL_Uart1_Init(void)
{
	static bool Uart1_Init = false;

	if(Uart1_Init != false)
		return;

	HAL_UART_Receive_DMA(&huart1, Uart1_RxBuffer.dataBuf, sizeof(Uart1_RxBuffer.dataBuf));
	__HAL_UART_CLEAR_IDLEFLAG(&huart1);
	__HAL_UART_ENABLE_IT(&huart1, UART_IT_IDLE);

	Uart1_Init = true;
}


/**
 * @funNm
 * @brief
 * @paramַ
 * @param
 * @retval bool
 */
bool HAL_Uart1_Send(uint8_t* pBuf, uint16_t len)
{
	bool state = false;

	if(HAL_UART_Transmit(&huart1, pBuf, len, 0x100) == HAL_OK)//
		state = true;

	return state;
}

/** 
 * @funNm
 * @brief
 * @param	void
 * @retval void
 * @note
 */
void HAL_Uart1_IDLE(void)//232
{
	if((__HAL_UART_GET_FLAG(&huart1, UART_FLAG_IDLE) != RESET))  
	{
		__HAL_UART_CLEAR_IDLEFLAG(&huart1);
		HAL_UART_DMAStop(&huart1);

		Uart1_RxBuffer.dataSize = U1_Rx_Len - __HAL_DMA_GET_COUNTER(&hdma_usart1_rx);
		HAL_Uart1_Callback(Uart1_RxBuffer.dataBuf, Uart1_RxBuffer.dataSize);

		memset(Uart1_RxBuffer.dataBuf, '\0', U1_Rx_Len);
		HAL_UART_Receive_DMA(&huart1, Uart1_RxBuffer.dataBuf, U1_Rx_Len);
	}
}

__weak void HAL_Uart1_Callback(uint8_t*  pBuf, uint16_t len)
{
	if(print_modbus_crc(pBuf,len) == 1)
	{
		uint8_t device_id = pBuf[0];
		if( device_id == devID)
		{
			if(pBuf[1] == 0x05)
			{
				Modbus05Request mModbusRequest;
				if(sizeof(mModbusRequest) == len)
				{
					memcpy(&mModbusRequest,pBuf,len);
					uint8_t coil_status = mModbusRequest.coil_status;
					uint16_t coil_address = mModbusRequest.coil_address;
					uint16_t coil_swap = coil_address<<8;
					coil_address = (coil_address>>8)|(coil_swap);
					if(coil_status == 0xff)//打开
					{
						if(coil_address == 0x01)
						{
							mOneCoidData1.Coil_state = 1;
							mOneCoidData1.exec_state = 1;
							mOneCoidData1.exec_time = 0;
						}else if(coil_address == 0x02)
						{
							mOneCoidData2.Coil_state = 1;
							mOneCoidData2.exec_state = 1;
							mOneCoidData2.exec_time = 0;

						}else if(coil_address == 0x03)
						{
							mOneCoidData3.Coil_state = 1;
							mOneCoidData3.exec_state = 1;
							mOneCoidData3.exec_time = 0;
						}else if(coil_address == 0x04)
						{
							mOneCoidData4.Coil_state = 1;
							mOneCoidData4.exec_state = 1;
							mOneCoidData4.exec_time = 0;

						}else if(coil_address == 0x05)
						{
							mOneCoidData5.Coil_state = 1;
							mOneCoidData5.exec_state = 1;
							mOneCoidData5.exec_time = 0;

						}else if(coil_address == 0x06)
						{
							mOneCoidData6.Coil_state = 1;
							mOneCoidData6.exec_state = 1;
							mOneCoidData6.exec_time = 0;

						}else if(coil_address == 0x07)
						{
							mOneCoidData7.Coil_state = 1;
							mOneCoidData7.exec_state = 1;
							mOneCoidData7.exec_time = 0;

						}else if(coil_address == 0x08)
						{
							mOneCoidData8.Coil_state = 1;
							mOneCoidData8.exec_state = 1;
							mOneCoidData8.exec_time = 0;
						}
					}else{   //关闭
						if(coil_address == 0x01)
						{
							mOneCoidData1.Coil_state = 0;
							mOneCoidData1.exec_state = 1;
							mOneCoidData1.exec_time = 0;
						}else if(coil_address == 0x02)
						{
							mOneCoidData2.Coil_state = 0;
							mOneCoidData2.exec_state = 1;
							mOneCoidData2.exec_time = 0;

						}else if(coil_address == 0x03)
						{
							mOneCoidData3.Coil_state = 0;
							mOneCoidData3.exec_state = 1;
							mOneCoidData3.exec_time = 0;
						}else if(coil_address == 0x04)
						{
							mOneCoidData4.Coil_state = 0;
							mOneCoidData4.exec_state = 1;
							mOneCoidData4.exec_time = 0;

						}else if(coil_address == 0x05)
						{
							mOneCoidData5.Coil_state = 0;
							mOneCoidData5.exec_state = 1;
							mOneCoidData5.exec_time = 0;

						}else if(coil_address == 0x06)
						{
							mOneCoidData6.Coil_state = 0;
							mOneCoidData6.exec_state = 1;
							mOneCoidData6.exec_time = 0;

						}else if(coil_address == 0x07)
						{
							mOneCoidData7.Coil_state = 0;
							mOneCoidData7.exec_state = 1;
							mOneCoidData7.exec_time = 0;

						}else if(coil_address == 0x08)
						{
							mOneCoidData8.Coil_state = 0;
							mOneCoidData8.exec_state = 1;
							mOneCoidData8.exec_time = 0;
						}
					}
					Modbus05Response response_buffer = {0};
					create_modbus_05_response((uint8_t *)&response_buffer,&mModbusRequest);
					HAL_Uart1_Send((uint8_t *)&response_buffer, sizeof(Modbus05Response));
				}
			}else if(pBuf[1] == 0x0f){
				Modbus0FRequest *request = (Modbus0FRequest *)pBuf;
				uint16_t coil_num = request->quantity_of_coils;
				uint16_t coil_num_swap = coil_num<<8;
				coil_num = (coil_num>>8)|(coil_num_swap);      // 线圈数量
				//uint8_t byte_num = request->byte_count;        // 字节数
				uint8_t cail_data = request->coil_data[0];    // 线圈数据（最多支持256个线圈）  最低位是最高位
				if(coil_num > 8)
				{
					coil_num = 8;
				}

				if((max_lock_state == 1)&&(open_dev_state == 1))
				{
					mMoreCoidData.Coil_num = coil_num;
					mMoreCoidData.exec_current_pos = 0;
					mMoreCoidData.exec_state = 1;
					mMoreCoidData.exec_time = 0;
					int i = 0;
					memset(mMoreCoidData.CoilData,0x00,8);

					for(i = 0;i < 8;i++)
					{
						if((cail_data >> i)&(0x01) == 0x01)  // i == 0时，第一个继电器
						{
							mMoreCoidData.CoilData[i] = 1;
						}else {
							mMoreCoidData.CoilData[i] = 0;
						}

					}
				}
				Modbus0FResponse response_buffer = {0};
				create_modbus_0F_response((uint8_t *)&response_buffer, request);
				HAL_Uart1_Send((uint8_t *)&response_buffer, sizeof(Modbus0FResponse));
			}
		}
	}
}

void HAL_Uart3_Init(void)
{
	static bool Uart3_Init = false;

	if(Uart3_Init != false)
		return;

	HAL_UART_Receive_DMA(&huart3, Uart3_RxBuffer.dataBuf, sizeof(Uart3_RxBuffer.dataBuf));
	__HAL_UART_CLEAR_IDLEFLAG(&huart3);
	__HAL_UART_ENABLE_IT(&huart3, UART_IT_IDLE);

	Uart3_Init = true;
}


/**
 * @funNm
 * @brief
 * @paramַ
 * @param
 * @retval bool
 */
bool HAL_Uart3_Send(uint8_t* pBuf, uint16_t len)
{
	bool state = false;

	if(HAL_UART_Transmit(&huart3, pBuf, len, 0x100) == HAL_OK)//
		state = true;

	return state;
}

/**
 * @funNm
 * @brief
 * @param	void
 * @retval void
 * @note
 */
void HAL_Uart3_IDLE(void)//485
{
	if((__HAL_UART_GET_FLAG(&huart3, UART_FLAG_IDLE) != RESET))
	{
		__HAL_UART_CLEAR_IDLEFLAG(&huart3);
		HAL_UART_DMAStop(&huart3);

		Uart3_RxBuffer.dataSize = U1_Rx_Len -__HAL_DMA_GET_COUNTER(&hdma_usart3_rx);
		HAL_Uart3_Callback(Uart3_RxBuffer.dataBuf, Uart3_RxBuffer.dataSize);

		memset(Uart3_RxBuffer.dataBuf, '\0', U1_Rx_Len);
		HAL_UART_Receive_DMA(&huart3, Uart3_RxBuffer.dataBuf, U1_Rx_Len);
	}
}

__weak void HAL_Uart3_Callback(uint8_t*  pBuf, uint16_t len)
{
	if(print_modbus_crc(pBuf,len) == 1)
	{
		uint8_t device_id = pBuf[0];
		if( device_id == devID)
		{
			if(pBuf[1] == 0x05)
			{
				Modbus05Request mModbusRequest;
				if(sizeof(mModbusRequest) == len)
				{
					memcpy(&mModbusRequest,pBuf,len);
					uint8_t coil_status = mModbusRequest.coil_status;
					uint16_t coil_address = mModbusRequest.coil_address;
					uint16_t coil_swap = coil_address<<8;
					coil_address = (coil_address>>8)|(coil_swap);
					if(coil_status == 0xff)//打开
					{
						if(coil_address == 0x01)
						{
							mOneCoidData1.Coil_state = 1;
							mOneCoidData1.exec_state = 1;
							mOneCoidData1.exec_time = 0;
						}else if(coil_address == 0x02)
						{
							mOneCoidData2.Coil_state = 1;
							mOneCoidData2.exec_state = 1;
							mOneCoidData2.exec_time = 0;

						}else if(coil_address == 0x03)
						{
							mOneCoidData3.Coil_state = 1;
							mOneCoidData3.exec_state = 1;
							mOneCoidData3.exec_time = 0;
						}else if(coil_address == 0x04)
						{
							mOneCoidData4.Coil_state = 1;
							mOneCoidData4.exec_state = 1;
							mOneCoidData4.exec_time = 0;

						}else if(coil_address == 0x05)
						{
							mOneCoidData5.Coil_state = 1;
							mOneCoidData5.exec_state = 1;
							mOneCoidData5.exec_time = 0;

						}else if(coil_address == 0x06)
						{
							mOneCoidData6.Coil_state = 1;
							mOneCoidData6.exec_state = 1;
							mOneCoidData6.exec_time = 0;

						}else if(coil_address == 0x07)
						{
							mOneCoidData7.Coil_state = 1;
							mOneCoidData7.exec_state = 1;
							mOneCoidData7.exec_time = 0;

						}else if(coil_address == 0x08)
						{
							mOneCoidData8.Coil_state = 1;
							mOneCoidData8.exec_state = 1;
							mOneCoidData8.exec_time = 0;
						}
					}else{   //关闭
						if(coil_address == 0x01)
						{
							mOneCoidData1.Coil_state = 0;
							mOneCoidData1.exec_state = 1;
							mOneCoidData1.exec_time = 0;
						}else if(coil_address == 0x02)
						{
							mOneCoidData2.Coil_state = 0;
							mOneCoidData2.exec_state = 1;
							mOneCoidData2.exec_time = 0;

						}else if(coil_address == 0x03)
						{
							mOneCoidData3.Coil_state = 0;
							mOneCoidData3.exec_state = 1;
							mOneCoidData3.exec_time = 0;
						}else if(coil_address == 0x04)
						{
							mOneCoidData4.Coil_state = 0;
							mOneCoidData4.exec_state = 1;
							mOneCoidData4.exec_time = 0;

						}else if(coil_address == 0x05)
						{
							mOneCoidData5.Coil_state = 0;
							mOneCoidData5.exec_state = 1;
							mOneCoidData5.exec_time = 0;

						}else if(coil_address == 0x06)
						{
							mOneCoidData6.Coil_state = 0;
							mOneCoidData6.exec_state = 1;
							mOneCoidData6.exec_time = 0;

						}else if(coil_address == 0x07)
						{
							mOneCoidData7.Coil_state = 0;
							mOneCoidData7.exec_state = 1;
							mOneCoidData7.exec_time = 0;

						}else if(coil_address == 0x08)
						{
							mOneCoidData8.Coil_state = 0;
							mOneCoidData8.exec_state = 1;
							mOneCoidData8.exec_time = 0;
						}
					}
					Modbus05Response response_buffer = {0};
					create_modbus_05_response((uint8_t *)&response_buffer,&mModbusRequest);
					HAL_Uart3_Send((uint8_t *)&response_buffer, sizeof(Modbus05Response));
				}
			}else if(pBuf[1] == 0x0f){
				Modbus0FRequest *request = (Modbus0FRequest *)pBuf;
				uint16_t coil_num = request->quantity_of_coils;
				uint16_t coil_num_swap = coil_num<<8;
				coil_num = (coil_num>>8)|(coil_num_swap);      // 线圈数量
				//uint8_t byte_num = request->byte_count;        // 字节数
				uint8_t cail_data = request->coil_data[0];    // 线圈数据（最多支持256个线圈）  最低位是最高位
				if(coil_num > 8)
				{
					coil_num = 8;
				}

				if((max_lock_state == 1)&&(open_dev_state == 1))
				{
					mMoreCoidData.Coil_num = coil_num;
					mMoreCoidData.exec_current_pos = 0;
					mMoreCoidData.exec_state = 1;
					mMoreCoidData.exec_time = 0;
					int i = 0;
					memset(mMoreCoidData.CoilData,0x00,8);

					for(i = 0;i < 8;i++)
					{
						if((cail_data >> i)&(0x01) == 0x01)  // i == 0时，第一个继电器
						{
							mMoreCoidData.CoilData[i] = 1;
						}else {
							mMoreCoidData.CoilData[i] = 0;
						}

					}
				}
				Modbus0FResponse response_buffer = {0};
				create_modbus_0F_response((uint8_t *)&response_buffer, request);
				HAL_Uart3_Send((uint8_t *)&response_buffer, sizeof(Modbus0FResponse));
			}
		}
	}
}































